package com.alex.engine;

public class Main
{
    private static final int SIRINA = 800; // privatna staticna finalna int vrednost koja nosi ime SIRINA i ima vrednost od 800.
    private static final int VISINA = 600; // privatna staticna finalna int vrednost koja nosi ime VISINA i ima vrednost od 600.
    
    private static final String NAZIV = "OpenGL-R&D"; // privatna staticna finalna String vrednost koja nosi ime NAZIV i ima vrednost "OpenGL-R&D".
    
    private boolean daLiRadi; // Setup bool koji nam ce sluzi da sred start, run i stop metode.
    
    // Sinhronizacija pocinje. Random naziv koji sluzi samo kao referenca (znaci nije bukvalan). Ne znam da li jos uvek da koristim globalne ili lokalne promenljive.
    private static final double FREJM_LIMIT = 1000.0D;
    private static final double FREJM_VREME = 1.0D / FREJM_LIMIT;
    
    private static long previousTime;
    private static double unprocessedTime; // Takodje se zove i delta. Jos koliko puta trebamo da update-umo.
    private static long currentTime;
    private static long passedTime;
    
    private static boolean daLiDaRenderuje; // Ili shouldRender
    
    private static int framesPerSecond;
    private static long frameCounter; // Frejmovi po sekunki / frames per second
    // Sinhronizacija zavrsava.
    
    private Game game;
    
    // Konstruktor.
    Main()
    {
        daLiRadi = false; // Pocetna vrednost ove promenljive je false.
        game = new Game();
    }
    
    // Main metoda.
    public static void main(String[] args)
    {
        Window.createWindow(SIRINA, VISINA, NAZIV);
        
        Main mGame = new Main(); // Zove se mGame da bih ga raspoznao od Game game objekta.
        mGame.start();
    }
    
    // Start metoda
    private void start()
    {
        if (daLiRadi == true) // Ako je kojim slucajem daLiRadi == true onda ima da se javi greska i program ima da se prekine.
        {
            System.err.println("Boolean daLiRadi is already set to true! Exiting program.");
            System.exit(1);
        }
        
        daLiRadi = true; // Moramo da da promenimo vrednost bool-a. Jer ako ne promenimo program se nikad nece pokrenuti.
        run(); // Pozivamo run metodu.
    }
    
    // Run metoda
    private void run()
    {
        //final double FREJM_VREME = 1.0D / FREJM_LIMIT;
            
        previousTime = Time.getTime();
        unprocessedTime = 0.0D;
        
        framesPerSecond = 0;
        frameCounter = 0;
        
        while(daLiRadi == true) // Ako je daLiRadi == true onda run metoda da se pokrene.
        {
            daLiDaRenderuje = false;
            
            currentTime = Time.getTime();
            passedTime = currentTime - previousTime;
            previousTime = currentTime;
            
            unprocessedTime += passedTime / (double) Time.SECOND;
            
            frameCounter += passedTime;
            
            while(unprocessedTime > FREJM_VREME)
            {
                daLiDaRenderuje = true;
                
                unprocessedTime -= FREJM_VREME;
                
                if (Window.isCloseRequested()) // Ako pritisnemo x u gornjem desnom uglu prozora onda ima da se pozove stop metoda.
                {
                    stop();
                }
                
                Time.setDetlta(FREJM_VREME);
                Input.update();
                
                game.input();
                game.update();
                
                if (frameCounter >= Time.SECOND)
                {
                    System.out.println("FPS: " + framesPerSecond);
                    framesPerSecond = 0;
                    frameCounter = 0;
                }
            }

            if (daLiDaRenderuje == true)
            {
                framesPerSecond++; // Mada moze da bude i posle ali sam paranoican.
                render(); // Ako ne pritisnemo onda se poziva render meotda iz Window klase.
            }
            else
            {
                try
                {
                    Thread.sleep(1L);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
        
        destroy(); // Kada daLiRadi == true vise nije istinito onda zelimo da unistimo sve sto je prikazano na ekranu.
    }
    
    // Stop metoda
    private void stop()
    {
        if (daLiRadi == false) // Ako je kojim slucajem daLiRadi == false onda ima da se javi greska i program ima da se prekine.
        {
            System.err.println("Boolean daLiRadi is already set to false! Exiting program.");
            System.exit(1);
        }
        
        daLiRadi = false; // Moramo da da promenimo vrednost bool-a. Jer ako ne promenimo program se nikad nece zaustaviti.
    }
    
    // Update metoda. Takodje uvek ide update metoda pa onda render metoda!
    private void update()
    {
        
    }
    
    // Redner metoda.
    private void render()
    {
        game.render();
        Window.render();
    }
    
    // Destroy metoda.
    private void destroy()
    {
        Window.destroyWindow();
    }
}
